// (C) Copyright 2012 Kystar. All rights reserved.

`timescale 1ns/100ps
`default_nettype none

module mcu_rx
(
    reset_n,
    sysclk,

    mcu_clk,
    mcu_cs,
    mcu_dat_in,

    clk_posedge,
    dat_begin,
    datin_valid,
    datin
);

    input                           reset_n;
    input                           sysclk;

    input                           mcu_clk;
    input                           mcu_cs;
    input                           mcu_dat_in;

    output                          clk_posedge;
    output                          dat_begin;
    output                          datin_valid;
    output          [7:0]           datin;

    reg                             datin_valid;
    reg             [7:0]           datin;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    reg             [2:0]           clk_buf;
    reg             [2:0]           cs_buf;
    reg             [2:0]           dat_in_buf;

    reg             [7:0]           shift_in;
    reg             [2:0]           bit_cnt;
    reg                             dat_latch;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    assign clk_posedge  = (!cs_buf[2]) && (!clk_buf[2]) && clk_buf[1];
    assign dat_begin    = (!cs_buf[1]) && cs_buf[2];
    always @(posedge sysclk or negedge reset_n) begin
        if(~reset_n) begin
            clk_buf <= 3'h0;
            cs_buf <= 3'h7;
            dat_in_buf <= 3'h0;
            end
        else begin
            clk_buf <= {clk_buf[1:0],mcu_clk};
            cs_buf <= {cs_buf[1:0],mcu_cs};
            dat_in_buf <= {dat_in_buf[1:0],mcu_dat_in};
            end
        end

    always @(posedge sysclk or negedge reset_n) begin
        if(~reset_n) begin
            shift_in <= 8'd0;
            bit_cnt <= 3'd0;
            end
        else if(cs_buf[2])
            bit_cnt <= 3'd0;
        else if(clk_posedge) begin
            shift_in <= {shift_in[6:0],dat_in_buf[2]};
            bit_cnt <= bit_cnt + 1'b1;
            end
        end

    always @(posedge sysclk or negedge reset_n) begin
        if(~reset_n)
            dat_latch <= 1'b0;
        else if(clk_posedge)
            dat_latch <= (bit_cnt == 3'b111);
        else
            dat_latch <= 1'b0;
        end

    always @(posedge sysclk or negedge reset_n) begin
        if(~reset_n) begin
            datin_valid <= 1'b0;
            datin <= 8'd0;
            end
        else if(dat_latch) begin
            datin_valid <= 1'b1;
            datin <= shift_in;
            end
        else
            datin_valid <= 1'b0;
        end

endmodule
`default_nettype wire
